package br.com.afi.pattern.wrapper;

import java.io.Serializable;

import br.com.afi.pattern.converter.Converter;
import br.com.afi.pattern.model.Model;
import br.com.afi.pattern.vo.ValueObject;

/**
 * Essa classe encapsula um {@link Model} ou um {@link ValueObject}, e provê a conversão entre os
 * dois tipos.
 * 
 * @author André de Fontana Ignacio
 * @param <E> Tipo do Model (Entity)
 * @param <V> Tipo do Value Object
 */
public class Wrapper<E extends Model<? extends Serializable>, V extends ValueObject> implements Serializable
{
	private static final long serialVersionUID = -4857945878516107609L;

	private Converter<E, V> converter;
	private E model;
	private V vo;

	/**
	 * Construtor
	 * 
	 * @param model Model (Entity)
	 * @param converter Conversor (Ideal que seja Singleton).
	 */
	public Wrapper( E model, Converter<E, V> converter )
	{
		super();
		this.model = model;
		this.converter = converter;
	}

	/**
	 * Construtor
	 * 
	 * @param vo Value Object
	 * @param converter Conversor (Ideal que possua sempre a mesma referência).
	 */
	public Wrapper( V vo, Converter<E, V> converter )
	{
		super();
		this.vo = vo;
		this.converter = converter;
	}

	/**
	 * Construtor
	 * 
	 * @param model Model (Entity)
	 * @param vo Value Object
	 * @param converter Conversor (Ideal que possua sempre a mesma referência).
	 */
	public Wrapper( E model, V vo, Converter<E, V> converter )
	{
		super();
		this.model = model;
		this.vo = vo;
		this.converter = converter;
	}

	/**
	 * Obtém o objeto como um Model (Entity).
	 * 
	 * @return Model (Entity)
	 */
	public E asModel()
	{
		return model != null ? model : converter.convertForward( vo );
	}

	/**
	 * Obtém o objeto como um Value Object.
	 * 
	 * @return Value Object
	 */
	public V asVO()
	{
		return vo != null ? vo : converter.convertReverse( model );
	}
}
